package socket;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.springframework.stereotype.Repository;

import dao.CommonDao;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import util.Log;
import util.Util;

/**
 * @author Administrator
 *
 *         设备消息处理类
 *
 * 心跳包
 * {id:"123",status:1,type:"heart"}
 *  
 *
 */
@Repository
public class Server {
	@Resource
	private CommonDao commonDao;

	/**
	 * 设备集合
	 * key id 设备 id
	 * value {ip,port} 设备ip和端口
	 */
	public static Map<String, JSONObject> mapIpPort = new HashMap<String, JSONObject>();
	/**
	 * 命令返回结果集合
	 * 命令执行是否成功，如果该HashMap有id的值那么就是执行成功
	 * key id 命令 id
	 * value {did,time} did设备id，time命令返回执行返回时间
	 */
	public static Map<String, JSONObject> mapCommandReturn = new HashMap<String, JSONObject>();
	
	/**
	 *发送的命令集合
	 */
	public static Map<String, JSONObject> mapCommand = new HashMap<String, JSONObject>();
	
	public static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	JSONObject jsonObjTemp=new JSONObject();

	/**
	 * 全局UDP发送网关
	 */
	public static DatagramSocket ds;
	
	public void init(){
		
		if(ds!=null){
			ds.disconnect();
			ds.close();
		}
		try {
			byte by[] = new byte[2000];
			DatagramPacket dp = new DatagramPacket(by, 0, by.length);
			ds = new DatagramSocket(1234);
			while (true) {
				System.out.println("wait for client...");
				ds.receive(dp);// 等待接收客户端消息，阻塞函数，一个dp就是一个客户端的一条消息
				Parse(dp);
				dp.setData(by, 0, by.length);
			}
		} catch (Exception e) {
			e.printStackTrace();
			try {
				Thread.sleep(5000);
				init();
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
		}
	}

	public void start() {
		try {
			
			new Thread(new Runnable() {
				@Override
				public void run() {
					clean();
				}
			}).start();
			
			new Thread(new Runnable() {
				@Override
				public void run() {
					outMapSize();
				}
			}).start();
			
			init();
			
			
			
			Log.outLog("server start success!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void outMapSize(){
		try {
//			System.out.println("-------------------------------------------------------------------");
//			System.out.println("mapIpPort.size():"+mapIpPort.size());
//			System.out.println("mapCommand.size():"+mapCommand.size());
//			System.out.println("mapCommandReturn.size():"+mapCommandReturn.size());
//			System.out.println("-------------------------------------------------------------------");
//			Thread.sleep(1000);
//			outMapSize();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	

	/**
	 * @param dp
	 * 解析设备返回的消息
	 */
	public void Parse(DatagramPacket dp) {
		try {
			String message = new String(dp.getData(), 0, dp.getLength());// 客户端消息
			System.out.println("recive a message "+sdf.format(new Date())+":"+message);
			SocketAddress socketAddress = dp.getSocketAddress();
			InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
			int clientPort = inetSocketAddress.getPort();
			String ip = inetSocketAddress.getAddress().getHostAddress();
			JSONObject messageJson = JSONObject.fromObject(message);
			String type = messageJson.getString("type");// 包类型
			if (type.equals("heart")) {
				String id=messageJson.getString("id");//设备id
				jsonObjTemp.put("ip", ip);
				jsonObjTemp.put("port", clientPort);
				jsonObjTemp.put("status", messageJson.getInt("status"));
				jsonObjTemp.put("time", new Date().getTime());
				mapIpPort.put(id, jsonObjTemp);
				
				messageJson.put("type", "heartReturn");
				byte buf[] = messageJson.toString().getBytes();
				dp.setData(buf, 0, buf.length);
				ds.send(dp);
			}
			
			if (type.equals("controlReturn")) {
				String id=messageJson.getString("id");//命令id
				String did=messageJson.getString("did");//设备id
				int command=messageJson.getInt("command");
				jsonObjTemp.put("did", did);
				jsonObjTemp.put("time", new Date().getTime());
				jsonObjTemp.put("command", command);//命令 0关闭，1打开，2确定设备是否在线（原样返回就行）
				mapCommandReturn.put(id, jsonObjTemp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

		

	/**
	 * 发送command
	 */
	public static boolean SendCommandThread(JSONObject jsonCommandData) {
		boolean result=false;
		try{
			String did=jsonCommandData.getString("did");//设备id
			String id=jsonCommandData.getString("id");//命令id
			JSONObject ipPort=mapIpPort.get(did);
			
			SocketAddress server = new InetSocketAddress(ipPort.getString("ip"), ipPort.getInt("port"));
			byte buff[] = jsonCommandData.toString().getBytes();
			DatagramPacket dp = new DatagramPacket(buff, 0, buff.length, server);
			ds.send(dp);// 发送命令到设备
			System.out.println(jsonCommandData.toString()+" "+sdf.format(new Date())+ " : 命令已发送！");
			
			jsonCommandData.put("time", new Date().getTime());//命令发送时间
			
			mapCommand.put(id, jsonCommandData);
			
			result=true;
			
//			new Thread(new Runnable() {
//				@Override
//				public void run() {
//					try {
//						Thread.sleep(2000);
//						SendCommandIfSuccess(id);
//					} catch (Exception e) {
//						e.printStackTrace();
//					}
//				}
//			}).start();
			
		} catch (Exception e) {
			result=false;
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 命令执行是否成功
	 * @param id 命令id
	 * @return
	 */
	public static boolean SendCommandIfSuccess(String id){
		boolean result=false;
		
		JSONObject jsonCommandReturnObj=mapCommandReturn.get(id);
		
		if(jsonCommandReturnObj!=null){//如果命令执行成功了，那么将命令从命令返回集合中移除
			result=true;
			mapCommandReturn.remove(id);
		}else{//如果命令没有被执行，那么将设备从设备集合中移除
			JSONObject jsonCommandObj=mapCommand.get(id);
			String did=jsonCommandObj.getString("did");//设备id
			mapIpPort.remove(did);
		}
		mapCommand.remove(id);
		return result;
	}
	
	/**
	 * 如果命令在集合里存储超过10秒，那么就将其删除
	 */
	public void clean(){
		try {
			for(Entry<String,JSONObject> entry:mapCommandReturn.entrySet()){
				JSONObject jsonCommandObj=entry.getValue();
				Long time=jsonCommandObj.getLong("time");//命令返回时间
				String did=jsonCommandObj.getString("did");
				int command=jsonCommandObj.getInt("command");
				Long timeNow=new Date().getTime();
				if(timeNow-time>10000){//如果命令在集合里存储超过10秒，那么就将其删除
					mapCommandReturn.remove(entry.getKey());
				}
			}
			
			for(Entry<String,JSONObject> entry:mapCommand.entrySet()){
				JSONObject jsonCommandObj=entry.getValue();
				Long time=jsonCommandObj.getLong("time");//命令发送时间
				String did=jsonCommandObj.getString("did");
				int command=jsonCommandObj.getInt("command");
				Long timeNow=new Date().getTime();
				if(timeNow-time>10000){//如果命令在集合里存储超过10秒，那么就将其删除
					mapCommand.remove(entry.getKey());
					if(command==2){
						mapIpPort.remove(did);
					}
				}
			}
			
			for(Entry<String,JSONObject> entry:mapIpPort.entrySet()){
				JSONObject jsonDevice=entry.getValue();
				Long time=jsonDevice.getLong("time");//命令发送时间
				Long timeNow=new Date().getTime();
				if(timeNow-time>10000){//如果命令在集合里存储超过10秒，那么就将其删除
					mapIpPort.remove(entry.getKey());
				}
			}
			
			Thread.sleep(10000);
			clean();
		} catch (Exception e) {
			clean();
			e.printStackTrace();
		}
	}
	
	
	public static JSONArray getDeviceStatus(JSONArray ids){
		JSONArray jData=new JSONArray();
//		jData.put("id", Util.uuid());//命令id
//		jData.put("did", id);//设备id
//		jData.put("command",2);
//		jData.put("type","control");
//		SendCommandThread(jData);
		
//		System.out.println(ids);
		
		for (int i = 0; i < ids.size(); i++) {
			String id=ids.get(i).toString();
			jData.add(mapIpPort.get(id));
		}
		
		return jData;
	}


	public static void main(String args[]) throws Exception {
		// Server.start();
	}
}
